package com.yzf.demo.demo.GenericParadigm;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by 于占峰 on 2020/3/27/027.
 * 泛型
 * <p>
 * ###### 参数类型 或者 类型参数化
 * <p>
 * ###### 	在不创建新的类型的情况瞎,通过泛型指定的不同类型来控制形参具体限制的类型
 * <p>
 * <p>
 * <p>
 * #### 泛型运用的意义:
 * <p>
 * ###### 	编译期间确定类型,保证类型安全;
 * <p>
 * ###### 	避免强制转换的逻辑;
 * <p>
 * ###### 	提高代码的重用率,增加程序的通用灵活性;
 */
public class DemoBean {


    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        //demo1();
        //demo2();
        //demo3();
        //demo4  可以传递任意形参的list集合
        ArrayList<String> list = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();
        ArrayList<DemoBean> list3 = new ArrayList<>();
        demo4(list);
        demo4(list2);
        demo4(list3);
        //demo5 要求必须是 Number 或 Number以下的形参集合
        ArrayList<Number> list4 = new ArrayList<>();
        ArrayList<Integer> list5 = new ArrayList<>();
        ArrayList<Double> list6 = new ArrayList<>();
        ArrayList<String> list7 = new ArrayList<>();
        demo5(list4);
        demo5(list5);
        demo5(list6);
        //类型为String的集合就不可以传入 因为不是Number或Number以下的形参
        //demo5(list7);

        //demo6 要求必须是 Integer 或 Integer以上的形参
        ArrayList<Number> list8 = new ArrayList<>();
        ArrayList<Integer> list9 = new ArrayList<>();
        ArrayList<Object> list10 = new ArrayList<>();
        ArrayList<Double> list11 = new ArrayList<>();
        ArrayList<String> list12 = new ArrayList<>();
        demo6(list8);
        demo6(list9);
        demo6(list10);
        //Double在下一级 不能String
        //demo6(list11);
        //String 与 Integer没有上下联系 不能传入
        //demo6(list12);

    }

    public static void demo1() {
        //限定类型的的集合使用
        ArrayList<String> list = new ArrayList<>();
        list.add("123");
        list.add("456");
        list.add("789");
        list.add("abc");
        list.forEach(val -> System.out.println(val.getClass().getTypeName()));
        //不限制类型转换的集合
        ArrayList list2 = new ArrayList();
        list2.add(1);
        list2.add("2");
        list2.add(3);
        list2.add("4");
        list2.forEach(val -> System.out.println(val.getClass().getTypeName()));

    }

    /**
     * #### 泛型类型擦除:
     * <p>
     * ###### 	泛型只在编译阶段有效,泛型类型在逻辑上可看成是多个不同的类型,但是其实质	都是同一个数据类型
     * <p>
     * ###### 	编译之后程序会采取去泛型化的措施
     */
    public static void demo2() {
        //限定类型的的集合使用
        ArrayList<String> list = new ArrayList<>();
        //不限制类型转换的集合
        ArrayList list2 = new ArrayList();
        System.out.println(list.getClass());
        System.out.println(list2.getClass());
        System.out.println(list.getClass() == list2.getClass());
    }

    /**
     * 对限定了形参类型集合进行反射操作
     */
    public static void demo3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //限定类型的的集合使用
        ArrayList<String> list = new ArrayList<>();
        list.add("123");
        list.add("456");
        list.add("789");
        list.add("abc");
        System.out.println("原存储长度:" + list.size());
        System.out.print("原元素类型:\n");
        list.forEach(val -> System.out.print(val.getClass().getTypeName() + " \n"));
        System.out.println("=================");
        //进行反射 调用add
        Class clazz = list.getClass();
        Method method = clazz.getDeclaredMethod("add", Object.class);
        method.invoke(list, 1000);
        //非泛型集合forEach遍历会报ClassCastException
        System.out.println("反射后的存储长度:" + list.size());
        System.out.println("=================");
    }

    /**
     * 无边界通配符
     * 无边界通配符 ? <?>
     */
    public static void demo4(ArrayList<?> list) {
        for (int i = 0; i <= list.size(); i++) {
            System.out.println(list.get(i));
        }
    }

    /**
     * 上界通配符 <? extends E>
     */
    public static void demo5(ArrayList<? extends Number> list) {
        for (int i = 0; i <= list.size(); i++) {
            System.out.println(list.get(i));
        }
    }

    /**
     * 下界通配符 <? super E>
     */
    public static void demo6(ArrayList<? super Integer> list) {
        for (int i = 0; i <= list.size(); i++) {
            System.out.println(list.get(i));
        }
    }


    public static void demoMethod(int count, String str) {
        System.out.println(count);
        System.out.println(str);
    }
}
